<?php

class StadiumController extends Controller
{
    public $layout='//layouts/jm_layout';
    public $dialog = NULL;
    public $dialogInfo = NULL;

    public function init()
    {
        parent::init();
        
        Yii::app()->clientScript->reset();
        $this->useBootstrap = false;
        $this->runAfterAction = false;
    }
	
    public function actionIndex()
	{
        $items = BSMResourceGroup::model()->getStadiumListByUser(Yii::app()->user->id, 20);
        if (count($items) == 0) {
            $items = BSMResourceGroup::model()->getStadiumListByRating(20);
        }
        
        $model = new SearchStadiumForm;
        $areaListData = BSMResourceGroup::model()->getAreaListData('_id', 'name');
        $sportTypes = BSMResourceGroup::model()->getSportTypes();
        
        $items = new CArrayDataProvider($items);
		$this->render('index', array(
            'dataProvider'=>$items,
            'model'=>$model,
            'sportTypes'=>$sportTypes,
            'areaListData'=>$areaListData,
            'dividerName'=>'',));
	}
    
    public function actionIndexResult()
    {
		$model = new SearchStadiumForm;
		$model->unsetAttributes();  // clear any default values
		if (isset($_GET['SearchStadiumForm'])) {
			$model->attributes = $_GET['SearchStadiumForm'];
        }
        
        $areaListData = BSMResourceGroup::model()->getAreaListData('_id', 'name');
        $sportTypes = BSMResourceGroup::model()->getSportTypes();

        $items = BSMResourceGroup::model()->getStadiumList($model->area, $model->sportType);

        $this->render('index', array(
            'dataProvider'=>new CArrayDataProvider($items,
                    array('pagination' => array('pageSize' => Util::PAGE_SIZE))),
            'model'=>$model,
            'sportTypes'=>$sportTypes,
            'areaListData'=>$areaListData,
            'dividerName'=>'',));
    }
    
    public function actionSearch()
    {
        $model = new SearchForm();
        $model->date = date('Y-m-d', strtotime('next monday'));
        $model->startTime = "08:00";
        $model->endTime = "23:00";
        $this->render('search', array(
                'model'=>$model,
                'sportTypes'=>BSMResourceGroup::model()->getSportTypes(),
            )
        );
    }
    
    function isAvailable($stadium, $sportType, $date, $startTime, $endTime)
    {
        $resources = BSMResource::model()->getResourceList($stadium->_id, $sportType);
        $bookableResources = BSMBookableResource::model()->getList($resources);
        $slotInfo = $this->getTimeslotInfo($bookableResources, $date, $startTime, $endTime);
        
        $count = 1;
        foreach ($resources as $id=>$resource) {
            $bookings = BSMBooking::model()->getList($resource->_id, $date, $startTime, $endTime);
            
            if ($slotInfo['count'] > 0) {
                $currDate = clone $slotInfo['min'];
                for ($i = 1; $i <= $slotInfo['count']; $i++) {
                    $status = $this->getBookStatus($resource, $bookableResources, $bookings, $slotInfo, $currDate);
                    if ($status->isAvailable()) {
                        return true;
                    }

                    $currDate->add(new DateInterval('PT1H'));
                }
            }
            
            $count++;
        }
        
        return count($resources) > 0 && $count < count($resources);
    }
    
    public function actionSearchResult()
    {
		$model = new SearchForm;
		$model->unsetAttributes();  // clear any default values
		if (isset($_GET['SearchForm'])) {
			$model->attributes = $_GET['SearchForm'];
        }
        
        $selectedDate = new DateTime($model->date);
        $rows = array();
        $stadiums = BSMResourceGroup::model()->getStadiumsBySportType($model->sportType, $model->name);
        foreach ($stadiums as $i => $stadium) {
            if ($this->isAvailable($stadium, $model->sportType, $selectedDate,
                    $model->startTime, $model->endTime)) {
                $rows[] = $stadium;
            }
        }
		
        $dataProvider=new CArrayDataProvider($rows, array('pagination' => array('pageSize' => Util::PAGE_SIZE)));

        $this->showBackButton = true;
        $this->pageTitle = Yii::t('site', 'Search Result');
        $this->render('searchResult',array(
			'dataProvider'=>$dataProvider,
            'dividerName'=>'',
            'sportType'=>$model->sportType,
            'date'=>$model->date,
		));
    }
    
    public function getTimeslots4Day($cronExpression, $date = NULL, $startTime = NULL, $endTime = NULL)
    {
        Yii::setPathOfAlias('Cron', Yii::getPathOfAlias('application.vendor.Cron'));
        
        $cron = Cron\CronExpression::factory($cronExpression);
        
        $result = array();
        
        $date1 = Controller::getDateTime($date);
        
        if ($startTime == NULL) {
            $startDate = NULL;
        } else {
            $startDate = Controller::getDateTime($date, $startTime);
        }

        if ($endTime == NULL) {
            $endDate = NULL;
        } else {
            $endDate = Controller::getDateTime($date, $endTime);
        }

        while (true)
        {
            $date2 = $cron->getNextRunDate($date1);
            
            if (Controller::isSameDay($date1, $date2)) {
                $date1 = $date2;

                if ($endDate != NULL && $date1 >= $endDate) {
                    break;
                }

                if ($startDate == NULL || $date1 >= $startDate) {
                    $result[] = $date1;
                }
            } else {
                break;
            }
        }
            
        return $result;
    }
    
    function getTimeslotInfo($bookableResources, $date, $startTime = NULL, $endTime = NULL)
    {
        $slotList = array();
        foreach ($bookableResources as $i=>$bookableResource) {
            if (!array_key_exists($bookableResource->timeslot_id, $slotList)) {
                $slotList[$bookableResource->timeslot_id] =
                        $this->getTimeslots4Day($bookableResource->timeslot->cron_value,
                        $date, $startTime, $endTime);
            }
        }
        
        $min = NULL;
        $max = NULL;
        foreach ($slotList as $id=>$slots) {
            if (count($slots) > 0) {
                if ($min == NULL || $min > $slots[0]) {
                    $min = $slots[0];
                }

                if ($max == NULL || $max < $slots[count($slots) - 1]) {
                    $max = $slots[count($slots) - 1];
                }
            }
        }
        
        $hours = ($min == NULL || $max == NULL) ? -1: Controller::dateDiffHours($min, $max);
        
        return array('min'=>$min, 'max'=>$max, 'count'=>($hours + 1), 'slotList'=>$slotList);
    }

    public function actionTimeslot($id, $sportType, $date = NULL, $startDate = NULL)
    {
        if ($date == NULL) {
            $date = date('Y-m-d', strtotime('next monday'));
        }
        
        $model = Controller::loadModel(BSMResourceGroup::model(), $id);
        $resources = BSMResource::model()->getResourceList($id, $sportType);
        $bookableResources = BSMBookableResource::model()->getList($resources);
        if (count($bookableResources) == 0) {
            $this->redirect(array('message', 'msg'=>'NO bookable resources found!'));
        } else {
            $slotInfo = $this->getTimeslotInfo($bookableResources, $date);

            $this->render('timeslot', array(
                    'model'=>$model,
                    'date'=>$date,
                    'startDate'=>$startDate,
                    'resources'=>$resources,
                    'bookableResources'=>$bookableResources,
                    'slotInfo'=>$slotInfo,
                 )
            );
        }
    }
    
    public function actionBooking()
    {
        $date = Yii::app()->request->getParam('date');
        $bookings = Yii::app()->request->getParam('bookings');

        if (Controller::isNullOrEmptyString($bookings)) {
            return;
        }
        
        $order = new BSMOrder;
        $order->status = BSMBooking::STATUS_BOOKED;
        $bookingList = array();
        
        $total_amount = 0;
        $items = explode(';', $bookings);
        foreach($items as $item) {
            if (!Controller::isNullOrEmptyString($item)) {
                $ba = explode('|', $item);

                $booking = new BSMBooking;
                $booking->bookable_resource_id = $ba[0];
                $booking->booking_status_id = BSMBooking::STATUS_BOOKED;
                
                $bookableResource = BSMBookableResource::model()->findByPk($booking->bookable_resource_id);
                if ($bookableResource == NULL) {
                    throw new Exception("Cannot find bookable resource");
                }
                
                $booking->booking_amount = $bookableResource->calcPrice();
                $total_amount += $booking->booking_amount;

                $start_time = $date . ' ' . $ba[1];
                $startTime = new DateTime($start_time);
                $startTime->add(new DateInterval('PT1H'));

                $booking->start_time = $start_time;
                $booking->end_time = $startTime->format("Y-m-d H:i:s");

                $bookingList[] = $booking;
            }
        }
        
        //$order->bookings = $bookingList;
        $order->amount = $total_amount;
        
        $transaction = $order->dbConnection->beginTransaction();
        try {
            if ($order->save()) {
                foreach ($bookingList as $booking) {
                    $booking->order_id = $order->_id;
                    $booking->save();
                }
                
                $transaction->commit();
                
                $this->redirect(array('pay','id'=>$order->_id));
            } else {
                $errorMsg = "";
                $errors = $order->getErrors();
                foreach ($errors as $key=>$value) {
                    $errorMsg .= $key . ":" . implode(',', $value) . "\n";
                }

                throw new Exception($errorMsg);
            }
        } catch (Exception $e) {
            $transaction->rollback();
            throw $e;
        }
    }
    
    public function actionPay($id)
    {
        $model = Controller::loadModel(BSMOrder::model(), $id);
        
        $this->render('pay',array(
			'model'=>$model,
		));
    }
    
    public function actionOrder($id)
    {
        $model = Controller::loadModel(BSMOrder::model(), $id);
        
        $this->render('order',array(
			'model'=>$model,
            'dataProvider'=>new CArrayDataProvider($model->bookings,
                    array('pagination' => array('pageSize' => Util::PAGE_SIZE))),
            'dividerName'=>'',
		));
    }
    
    public function actionCancelOrder()
    {
        $id = Yii::app()->request->getParam('WIDout_trade_no');
        $order = Controller::loadModel(BSMOrder::model(), $id);
        if ($order->status == BSMBooking::STATUS_CANCEL) {
            $this->redirect(array('site/message', 'msg'=>'This order has been cancelled'));
        } else if ($order->status == BSMBooking::STATUS_BOOKED) {
            $order->status = BSMBooking::STATUS_CANCEL;
            
            foreach ($order->bookings as $booking) {
                $booking->booking_status_id = BSMBooking::STATUS_CANCEL;
            }
            
            $transaction = $order->dbConnection->beginTransaction();
            try {
                if ($order->save()) {
                    foreach ($order->bookings as $booking) {
                        $booking->save();
                    }

                    $transaction->commit();

                    $this->redirect(array('message', 'msg'=>Yii::t('site', 'Order Cancelled')));
                } else {
                    $errorMsg = "";
                    $errors = $order->getErrors();
                    foreach ($errors as $key=>$value) {
                        $errorMsg .= $key . ":" . implode(',', $value) . "\n";
                    }

                    throw new Exception($errorMsg);
                }
            } catch (Exception $e) {
                $transaction->rollback();
                throw $e;
            }
        }
    }

	public function actionView($id)
	{
        $model = Controller::loadModel(BSMResourceGroup::model(), $id);
        $sportTypes = new CArrayDataProvider(BSMResourceGroup::model()->getSportTypeByStadium($model->_id));
        $favorite = BSMUserFavoriteGroup::model()->findIt($id, yii::app()->user->id);
        $commentCount = BSMComment::model()->getCount($id, "BSResourceGroup");
		$this->render('view',array(
			'model'=>$model,
            'sportTypes'=>$sportTypes,
            'favorite'=>$favorite,
            'commentCount'=>$commentCount,
            'dividerName'=>'',
		));
	}
    
    public function actionComments($id)
	{
        $model = Controller::loadModel(BSMResourceGroup::model(), $id);
        
        $items = BSMComment::model()->getList($id, "BSResourceGroup");
        
		$this->render('comments',array(
            'dataProvider'=>new CArrayDataProvider($items,
                array('keyField' => '_id',
                    'sort'=>array(
                        'attributes'=>array(
                             '_id',
                        ),
                    ),
                    'pagination' => array('pageSize'=>Util::PAGE_SIZE,)
                )
            ),
			'model'=>$model,
            'dividerName'=>'',
		));
	}
    
    public function actionAddComment($id)
    {
        $resourceType = Yii::app()->request->getParam('comment_type');
        $rating = Yii::app()->request->getParam('score');
        $title = Yii::app()->request->getParam('comment_name');
        $content = Yii::app()->request->getParam('comment_content');
        
        $comment = new BSMComment();
        $comment->resource_id = $id;
        $comment->resource_type = $resourceType;
        $comment->rating = $rating;
        $comment->user_id = Yii::app()->user->id;
        $comment->name = $title;
        $comment->comment = $content;

        $comment->space_id = Blyn::app()->getActiveSpace()->getId();
        $comment->app_id = Blyn::app()->getActiveApp()->getId();
        
        $comment->save();
        
        $avgRating = intval(BSMComment::calcAvgRating($id, $resourceType));
        
        if ($resourceType == "BSResourceGroup") {
            $model = Controller::loadModel(BSMResourceGroup::model(), $id);
            $model->rating = $avgRating;
            $model->save();
        }
        
        $commentCount = BSMComment::model()->getCount($id, $resourceType);
        echo '{"rating":'.$avgRating.',"count":'.$commentCount.'}';
    }

    // Uncomment the following methods and override them if needed
	/*
	public function filters()
	{
		// return the filter configuration for this controller, e.g.:
		return array(
			'inlineFilterName',
			array(
				'class'=>'path.to.FilterClass',
				'propertyName'=>'propertyValue',
			),
		);
	}

	public function actions()
	{
		// return external action classes, e.g.:
		return array(
			'action1'=>'path.to.ActionClass',
			'action2'=>array(
				'class'=>'path.to.AnotherActionClass',
				'propertyName'=>'propertyValue',
			),
		);
	}
	*/
    function isInTimeBlock($startTime, $endTime, $currDate, $timeBlock = 1)
    {
        $startDate = Controller::getDateTime($startTime);
        $endDate = Controller::getDateTime($endTime);
        
        $toDate = clone $currDate;
        $toDate->add(new DateInterval('PT'. $timeBlock .'H'));
        return (($startDate >= $currDate && $startDate < $toDate) ||
                ($endDate > $currDate && $endDate < $toDate));
    }
    
    function getBookStatus($resource, $bookableResources, $bookings, $slotInfo, $currDate, $timeBlock = 1)
    {
        $result = new BookStatus();
        
        foreach ($bookings as $id=>$booking) {
            if ($this->isInTimeBlock($booking->start_time, $booking->end_time, $currDate)) {
                $result->status = BookStatus::BOOKED;
                $result->bookableResourceId = $booking->bookable_resource_id;
                $result->byMe = $booking->user_id == yii::app()->user->id;
                $result->cancelable = $booking->user_id == yii::app()->user->id &&
                        $booking->booking_status_id == BSMBooking::STATUS_BOOKED;
                return $result; //booked
            }
        }
        
        if ($currDate < new DateTime()) {
            $result->status = BookStatus::UNAVAILABLE;
            return $result;
        }
        
        $bs = array();
        foreach ($bookableResources as $id=>$bookableResource) {
            if ($bookableResource->resource_id == $resource->_id) {
                $bs[$bookableResource->priority.$bookableResource->_id] = $bookableResource;
            }
        }
        
        krsort($bs);
        
        foreach ($bs as $key => $bookableResource) {
            $slots = $slotInfo['slotList'][$bookableResource->timeslot_id];
            foreach ($slots as $slot) {
                $endDate = clone $slot;
                $endDate->add(new DateInterval('PT1H'));
                if ($this->isInTimeBlock($slot, $endDate, $currDate)) {
                    $result->status = BookStatus::AVAILABLE;
                    $result->bookableResourceId = $bookableResource->_id;
                    return $result; //available
                }
            }
        }
        
        $result->status = BookStatus::UNAVAILABLE;
        return $result; //unavailable
    }
    
    function actionFavorites()
    {
        $items = BSMResourceGroup::model()->getStadiumListByUser(Yii::app()->user->id);
        
		$this->render('favorites',
            array('dataProvider'=>new CArrayDataProvider($items,
                    array('pagination' => array('pageSize' => Util::PAGE_SIZE))),
            'dividerName'=>'',));
    }
    
    function actionAddFavorite($id)
    {
        $model = BSMUserFavoriteGroup::model()->findIt($id, yii::app()->user->id);
        if ($model == null) {
            $model = new BSMUserFavoriteGroup;
            $model->group_id = $id;
            $model->user_id = yii::app()->user->id;
            $model->save();
        }
    }
    
    function actionRemoveFavorite($id)
    {
        BSMUserFavoriteGroup::model()->deleteAll('group_id = :groupId AND user_id = :userId',
                array('groupId'=>$id, 'userId'=>yii::app()->user->id));
    }
    
    function actionHistory()
    {
        $items = BSMOrder::model()->getList(yii::app()->user->id);
        $this->render('history', array(
            'dataProvider'=>new CArrayDataProvider($items, array('pagination' => array('pageSize' => Util::PAGE_SIZE))),
            'dividerName'=>'',
        ));
    }

    public function actionMessage($msg)
    {
        $this->render('message', array('message'=>$msg));
    }
}